package br.ufrn.dimap.ase.squid.metrics;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import br.ufrn.dimap.ase.squid.core.models.squidmodel.Feature;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Mapping;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.SquidModel;
import br.ufrn.dimap.ase.squid.core.models.util.ModelContent;
import br.ufrn.dimap.ase.squid.core.models.util.SquidModelContent;
import br.ufrn.dimap.ase.squid.metrics.views.tree.model.InfoNode;
import br.ufrn.dimap.ase.squid.metrics.views.tree.model.Resultado;
import br.ufrn.dimap.ase.squid.metrics.visitors.AbstractVisitor;

public abstract class AbstractMetrics extends AbstractVisitor {
	protected IProject project; 
	protected SquidModelContent analysisModelContent;
	protected ModelContent queryModelContent;
	protected SquidModel queryModel;
	protected String squidModelPath = "";
	
	protected Map<String, List<Mapping>> mapping;
	
	protected String result;
	protected List<InfoNode> infos;
	protected Resultado[] resultados;
	
	public void init() {
		project = getProject();

		this.iniciar();
	}
	public void init(IProject project) {
		this.project = project;
		
		this.iniciar();
	}
	private void iniciar() {
		this.result = "";
		this.infos = new ArrayList<InfoNode>();
		
		this.squidModelPath = project.getFullPath() + "/Squid/SquidModel.squidmodel";
		analysisModelContent = new SquidModelContent(squidModelPath);
		
		queryModelContent = new ModelContent();
		queryModel = queryModelContent.getAnalysisModel();
		
		mapping = indexarMapppingsFromFeatures();
	}
	
	/**
	 * Inicia os dados, calcula as metricas e mostra
	 * os resultados
	 */
	public void run() {
		this.init();
		
		this.runMetrics();
		
		this.showResults();
	}
	
	public Resultado[] run(IProject project, String feature) {
		this.init(project);
		
		this.runMetrics(feature);
		
		return resultados;
	}
	
	/**
	 * Metodo que calcula as metricas
	 */
	public abstract void runMetrics();
	/**
	 * Metodo que calcula as metricas apenas para uma feature
	 * @param feature
	 */
	public abstract void runMetrics(String feature);
	
	/**
	 * Mostra os resultados
	 */
	public void showResults() {
		Shell shell = new Shell();  
		shell.setLayout(new FillLayout());  
		shell.setSize(400, 400); shell.setLocation(300, 150);
		StyledText b1 = new StyledText(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);  
		b1.setText(result);
		b1.setEditable(false);
		shell.open ();  
	}

	protected Map<String, List<Mapping>> indexarMapppingsFromFeatures(){
		
		List<Mapping> mappings = this.analysisModelContent.getAllMappigns();
		
		Map<String, List<Mapping>> featuresToMappings = new HashMap<String, List<Mapping>>();
//		System.out.println("Testando " + mappings.size());
		EList<Feature> features=null;

		for(int i = 0; i < mappings.size(); i++){
			Mapping mapping = mappings.get(i);
			features = mapping.getFeatures();
			
			for(int j = 0; j < features.size(); j++){
				Feature feature = features.get(j);
				
				if (!featuresToMappings.containsKey(feature.getName())){
					featuresToMappings.put(feature.getName(), new ArrayList<Mapping>());
				}
				
				List<Mapping> listMappings = featuresToMappings.get(feature.getName());
				listMappings.add(mapping);
			
			}
		}
		return featuresToMappings;
		
	}
	
	public String getName() {
		return this.getClass().getSimpleName();
	}

	public String getPath() {		
		return  project.getFullPath() + "/Squid/Queries/"+this.getClass().getSimpleName()+".squidmodel";
	}
	
	protected IProject getProject(){
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
	    if (window != null)
	    {
	        IStructuredSelection selection = (IStructuredSelection) window.getSelectionService().getSelection();
	        Object firstElement = selection.getFirstElement();
	        if (firstElement instanceof IAdaptable)
	        {
	            return (IProject)((IAdaptable)firstElement).getAdapter(IProject.class);
	        }
	    }
	    return null;
	}

}
